home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / quicktime vr / vrmovies / vrmovies.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  34.2 KB  |  1,230 lines

  1. //////////
  2. //
  3. //    File:        VRMovies.c
  4. //
  5. //    Contains:    Support for QuickTime movie playback in VR nodes.
  6. //
  7. //    Written by:    Tim Monroe
  8. //                Some code borrowed from QTVRSamplePlayer by Bryce Wolfson.
  9. //
  10. //    Copyright:    © 1996-1998 by Apple Computer, Inc., all rights reserved.
  11. //
  12. //    Change History (most recent first):
  13. //
  14. //       <15>         06/23/99    rtm        added VRMoov_MacRGBToWinRGB and VRMoov_WinRGBToMacRGB
  15. //       <14>         06/22/99    rtm        more work on matrices; now everything works okay (AFAICT)
  16. //       <13>         06/21/99    rtm        added call to UpdateMovie to back buffer imaging procedure
  17. //       <12>         06/18/99    rtm        got movie matrices working correctly; added color picking to Windows
  18. //       <11>         06/17/99    rtm        reworked geometry of back buffer yet again; now we copy from the
  19. //                                    offscreen GWorld to back buffer using use DecompressSequenceFrameS
  20. //       <10>         05/16/99    rtm        added VRMoov_DumpWindowData; further work on geometry of back buffer
  21. //       <9>         05/15/99    rtm        reworked geometry handling to support horizontal back buffer in QT 4.0
  22. //       <8>         05/04/98    rtm        added automatic rotation of movie
  23. //       <7>         03/06/97    rtm        started to implement video masking
  24. //       <6>         03/05/97    rtm        added VRMoov_SetChromaColor; added fChromaColor to app data record
  25. //       <5>         03/04/97    rtm        fixed compositing problems at back buffer edges
  26. //       <4>         03/03/97    rtm        added VRMoov_SetVideoGraphicsMode to handle compositing
  27. //                                    without using an offscreen GWorld
  28. //       <3>         02/27/97    rtm        further development: borrowed some ideas from QTVRSamplePlayer;
  29. //                                    added VRMoov_SetEmbeddedMovieWidth etc.
  30. //       <2>         12/12/96    rtm        further development: borrowed some ideas from BoxMoov demo 
  31. //       <1>         12/11/96    rtm        first file 
  32. //       
  33. // This code draws the QuickTime movie frames into the back buffer, either directly
  34. // or indirectly (via an offscreen GWorld). Direct drawing gives the best performance,
  35. // but indirect drawing is necessary for some visual effects. 
  36. //
  37. //////////
  38.  
  39. // TO DO:
  40. // + finish video masking by custom 'hide' hot spots (so video goes *behind* such hot spots)
  41. // + verify that everything works okay if *images* are used instead of movies (scaling seems to be a problem)
  42.  
  43.  
  44. //////////
  45. //       
  46. // header files
  47. //       
  48. //////////
  49.  
  50. #include "VRMovies.h"
  51.  
  52.  
  53. //////////
  54. //       
  55. // constants
  56. //       
  57. //////////
  58.  
  59. const RGBColor            kClearColor = {0x0000, 0xffff, 0x0000};        // the default chroma key color
  60. const RGBColor            kBlackColor = {0x0000, 0x0000, 0x0000};
  61. const RGBColor            kWhiteColor = {0xffff, 0xffff, 0xffff};
  62.  
  63.  
  64. //////////
  65. //       
  66. // global variables
  67. //       
  68. //////////
  69.  
  70. #if TARGET_OS_MAC
  71. UserEventUPP            gColorFilterUPP = NULL;                        // UPP to our custom color picker dialog event filter
  72. #endif
  73.  
  74.  
  75. //////////
  76. //
  77. // VRMoov_InitWindowData
  78. // Initialize any window-specific data.
  79. //
  80. //////////
  81.  
  82. ApplicationDataHdl VRMoov_InitWindowData (WindowObject theWindowObject)
  83. {
  84. #pragma unused(theWindowObject)
  85.  
  86.     ApplicationDataHdl    myAppData;
  87.     
  88.     myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
  89.     if (myAppData != NULL) {
  90.         (**myAppData).fMovie = NULL;
  91.         (**myAppData).fOffscreenGWorld = NULL;
  92.         (**myAppData).fOffscreenPixMap = NULL;
  93.         (**myAppData).fPrevBBufGWorld = NULL;
  94.         (**myAppData).fMovieCenter.x = 0.0;
  95.         (**myAppData).fMovieCenter.y = 0.0;
  96.         (**myAppData).fMovieScale = 1.0;
  97.         (**myAppData).fMovieWidth = kDefaultEmbMovieWidth;
  98.         (**myAppData).fUseOffscreenGWorld = false;
  99.         (**myAppData).fUseMovieCenter = true;
  100.         (**myAppData).fQTMovieHasSound = false;
  101.         (**myAppData).fCompositeMovie = false;
  102.         (**myAppData).fUseHideRegion = false;
  103.         (**myAppData).fChromaColor = kClearColor;
  104.         (**myAppData).fHideRegion = NULL;
  105.         (**myAppData).fBackBufferIsHoriz = false;
  106.         (**myAppData).fImageDesc = NULL;
  107.         (**myAppData).fImageSequence = 0;
  108.         
  109.         SetIdentityMatrix(&(**myAppData).fMovieMatrix);
  110.         SetIdentityMatrix(&(**myAppData).fOrigMovieMatrix);
  111.         
  112.         // create a new routine descriptor
  113.         (**myAppData).fBackBufferProc = NewQTVRBackBufferImagingProc(VRMoov_BackBufferImagingProc);
  114.     }
  115.  
  116. #if TARGET_OS_MAC    
  117.     if (gColorFilterUPP == NULL)
  118.         gColorFilterUPP = NewUserEventProc(VRMoov_ColorDialogEventFilter);
  119. #endif
  120.  
  121.     return(myAppData);
  122. }
  123.  
  124.  
  125. //////////
  126. //
  127. // VRMoov_DumpWindowData
  128. // Dispose of any window-specific data.
  129. //
  130. //////////
  131.  
  132. void VRMoov_DumpWindowData (WindowObject theWindowObject)
  133. {
  134.     ApplicationDataHdl        myAppData = NULL;
  135.  
  136.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  137.     if (myAppData == NULL)
  138.         return;
  139.  
  140.     VRMoov_DumpEmbeddedMovie(theWindowObject);
  141.     
  142.     DisposeRoutineDescriptor((**myAppData).fBackBufferProc);
  143. }
  144.  
  145.  
  146. ///////////
  147. //
  148. // VRMoov_GetEmbeddedMovie
  149. // Get the QuickTime movie to be embedded in a panorama.
  150. // Returns a Boolean to indicate success (true) or failure (false).
  151. //
  152. //////////
  153.  
  154. Boolean VRMoov_GetEmbeddedMovie (WindowObject theWindowObject)
  155. {
  156.     StandardFileReply        myReply;
  157.     short                    myNumTypes = 1;
  158.     SFTypeList                myTypes = {MovieFileType, 0};
  159.  
  160.     // do some preliminary parameter checking
  161.     if (theWindowObject == NULL)
  162.         return(false);
  163.     
  164.     if (!IsWindowObjectOurs(theWindowObject))
  165.         return(false);
  166.     
  167.     // elicit the movie file from user
  168.     StandardGetFilePreview(NULL, myNumTypes, myTypes, &myReply);
  169.     if (!myReply.sfGood) {
  170.         VRMoov_DumpEmbeddedMovie(theWindowObject);     // clean up any existing embedded movie
  171.         return(false);
  172.     }
  173.         
  174.     return(VRMoov_LoadEmbeddedMovie(&myReply.sfFile, theWindowObject));
  175. }
  176.  
  177.  
  178. //////////
  179. //
  180. // VRMoov_LoadEmbeddedMovie
  181. // Load the QuickTime movie in the specified file.
  182. // Returns a Boolean to indicate success (true) or failure (false).
  183. //
  184. //////////
  185.  
  186. Boolean VRMoov_LoadEmbeddedMovie (FSSpec *theMovieFile, WindowObject theWindowObject)
  187. {
  188.     short                    myMovieFileRef;
  189.     Movie                    myMovie;
  190.     GWorldPtr                myGWorld = NULL;
  191.     Rect                    myRect;
  192.     ApplicationDataHdl        myAppData = NULL;
  193.     OSErr                    myErr = paramErr;
  194.         
  195.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  196.     if (myAppData == NULL)
  197.         goto bail;
  198.  
  199.     HLock((Handle)myAppData);
  200.     
  201.     //////////
  202.     //
  203.     // open the movie file and the movie
  204.     //
  205.     //////////
  206.     
  207.     myErr = OpenMovieFile(theMovieFile, &myMovieFileRef, fsRdPerm);
  208.     if (myErr != noErr)
  209.         goto bail;
  210.  
  211.     myErr = NewMovieFromFile(&myMovie, myMovieFileRef, NULL, (StringPtr)NULL, newMovieActive, NULL);
  212.     if (myErr != noErr)
  213.         goto bail;
  214.  
  215.     //////////
  216.     //
  217.     // get the movie geometry
  218.     //
  219.     //////////
  220.     
  221.     GetMovieBox(myMovie, &myRect);
  222.     GetMovieMatrix(myMovie, &(**myAppData).fOrigMovieMatrix);
  223.     MacOffsetRect(&myRect, -myRect.left, -myRect.top);
  224.     SetMovieBox(myMovie, &myRect);
  225.  
  226.     // keep track of the movie and movie rectangle (in our app-specific data structure)
  227.     (**myAppData).fMovie = myMovie;
  228.     (**myAppData).fMovieBox = myRect;
  229.  
  230.     // determine the orientation of the back buffer
  231.     (**myAppData).fBackBufferIsHoriz = QTVRUtils_IsBackBufferHorizontal((**theWindowObject).fInstance);
  232.     
  233.     // get rid of any existing offscreen graphics world
  234.     if ((**myAppData).fOffscreenGWorld != NULL) {
  235.         DisposeGWorld((**myAppData).fOffscreenGWorld);
  236.         (**myAppData).fOffscreenGWorld = NULL;
  237.     }
  238.     
  239.     // clear out any existing custom cover/uncover functions and reset the video media graphics mode
  240.     // (these may have been modified for direct-screen drawing)
  241.     SetMovieCoverProcs(myMovie, NULL, NULL, 0L);
  242.     VRMoov_SetVideoGraphicsMode(myMovie, myAppData, false);
  243.     
  244.     //////////
  245.     //
  246.     // if necessary, create an offscreen graphics world
  247.     //
  248.     // this is where we'll image the movie before copying it into the back buffer
  249.     // when we want to do special effects
  250.     //
  251.     //////////
  252.     
  253.     if ((**myAppData).fUseOffscreenGWorld) {
  254.         myErr = NewGWorld(&myGWorld, 0, &myRect, NULL, NULL, 0);
  255.         (**myAppData).fOffscreenGWorld = myGWorld;
  256.         (**myAppData).fOffscreenPixMap = GetGWorldPixMap(myGWorld);
  257.         
  258.         // make an image description, which is needed by DecompressSequenceBegin
  259.         LockPixels((**myAppData).fOffscreenPixMap);
  260.         MakeImageDescriptionForPixMap((**myAppData).fOffscreenPixMap, &((**myAppData).fImageDesc));
  261.         UnlockPixels((**myAppData).fOffscreenPixMap);
  262.     } else {
  263.         // set the video media graphics mode to drop out the chroma key color in a movie;
  264.         // we also need to install an uncover function that doesn't erase the uncovered region
  265.         if ((**myAppData).fCompositeMovie) {
  266.             VRMoov_SetVideoGraphicsMode(myMovie, myAppData, true);
  267.             SetMovieCoverProcs(myMovie, NewMovieRgnCoverProc(VRMoov_UncoverProc), NULL, (long)theWindowObject);
  268.         }
  269.     }
  270.     
  271.     //////////
  272.     //
  273.     // install the back-buffer imaging procedure
  274.     //
  275.     //////////
  276.     
  277.     if ((**theWindowObject).fInstance != NULL)
  278.         myErr = VRMoov_InstallBackBufferImagingProc((**theWindowObject).fInstance, theWindowObject);
  279.         
  280.     // start the movie playing in a loop
  281.     VRMoov_LoopEmbeddedMovie(myMovie);
  282.  
  283. bail:
  284.     // we don't want to edit the embedded movie, so we can close the movie file
  285.     if (myMovieFileRef != 0)
  286.         CloseMovieFile(myMovieFileRef);
  287.         
  288.     HUnlock((Handle)myAppData);
  289.  
  290.     return(myErr == noErr);
  291. }
  292.     
  293.     
  294. //////////
  295. //
  296. // VRMoov_LoopEmbeddedMovie
  297. // Start the QuickTime movie playing in a loop.
  298. //
  299. //////////
  300.  
  301. void VRMoov_LoopEmbeddedMovie (Movie theMovie)
  302. {
  303.     TimeBase        myTimeBase;
  304.  
  305.     // throw the movie into loop mode
  306.     myTimeBase = GetMovieTimeBase(theMovie);
  307.     SetTimeBaseFlags(myTimeBase, GetTimeBaseFlags(myTimeBase) | loopTimeBase);
  308.  
  309.     // start playing the movie
  310.     StartMovie(theMovie);
  311. }
  312.     
  313.  
  314. //////////
  315. //
  316. // VRMoov_DumpEmbeddedMovie
  317. // Stop any existing embedded movie from playing and then clean up.
  318. //
  319. //////////
  320.  
  321. void VRMoov_DumpEmbeddedMovie (WindowObject theWindowObject)
  322. {
  323.     ApplicationDataHdl        myAppData;
  324.  
  325.     if (theWindowObject == NULL) 
  326.         goto bail;
  327.     
  328.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  329.     if (myAppData == NULL)
  330.         goto bail;
  331.     
  332.     // if we have an embedded movie, stop it from playing and dispose of it
  333.     if ((**myAppData).fMovie != NULL) {
  334.         StopMovie((**myAppData).fMovie);
  335.         DisposeMovie((**myAppData).fMovie);
  336.         (**myAppData).fMovie = NULL;
  337.     }
  338.     
  339.     // get rid of any existing offscreen graphics world
  340.     if ((**myAppData).fOffscreenGWorld != NULL) {
  341.         DisposeGWorld((**myAppData).fOffscreenGWorld);
  342.         (**myAppData).fOffscreenGWorld = NULL;
  343.     }
  344.     
  345.     // clear the existing back buffer imaging proc
  346.     QTVRSetBackBufferImagingProc((**theWindowObject).fInstance, NULL, 0, NULL, 0);
  347.     
  348.     // clear out any other movie-specific data
  349.     (**myAppData).fPrevBBufGWorld = NULL;
  350.     MacSetRect(&(**myAppData).fPrevBBufRect, 0, 0, 0, 0);
  351.     
  352.     MacSetRect(&(**myAppData).fMovieBox, 0, 0, 0, 0);
  353.     SetIdentityMatrix(&(**myAppData).fMovieMatrix);
  354.     SetIdentityMatrix(&(**myAppData).fOrigMovieMatrix);
  355.     
  356.     if ((**myAppData).fImageDesc != NULL) {
  357.         DisposeHandle((Handle)(**myAppData).fImageDesc);
  358.         (**myAppData).fImageDesc = NULL;
  359.     }
  360.     
  361.     VRMoov_RemoveDecompSeq(theWindowObject);
  362.     
  363.     // make sure the back buffer is clean
  364.     QTVRRefreshBackBuffer((**theWindowObject).fInstance, 0);
  365.  
  366. bail:
  367.     return;
  368. }
  369.     
  370.  
  371. //////////
  372. //
  373. // VRMoov_InstallBackBufferImagingProc
  374. // Install a back buffer imaging procedure.
  375. // (This routine might sometimes be called to move or resize the area of interest within the panorama.)
  376. //
  377. //////////
  378.  
  379. OSErr VRMoov_InstallBackBufferImagingProc (QTVRInstance theInstance, WindowObject theWindowObject)
  380. {
  381.     ApplicationDataHdl        myAppData;
  382.     QTVRAreaOfInterest        myArea;
  383.     float                    myWidth, myHeight;
  384.     OSErr                    myErr = noErr;
  385.  
  386.     //////////
  387.     //
  388.     // initialize; clean up any existing back buffer procedure
  389.     //
  390.     //////////
  391.     
  392.     if ((theInstance == NULL) || (theWindowObject == NULL)) 
  393.         return(paramErr);
  394.  
  395.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  396.     if (myAppData == NULL) 
  397.         return(paramErr);
  398.  
  399.     HLock((Handle)myAppData);
  400.     
  401.     // remove any existing back buffer imaging procedure
  402.     if ((**myAppData).fBackBufferProc != NULL)
  403.         QTVRSetBackBufferImagingProc(theInstance, NULL, 0, NULL, 0);
  404.  
  405.     //////////
  406.     //
  407.     // set the area of interest
  408.     //
  409.     // the panAngle and tiltAngle fields define the top-left corner, in panorama space, of the area of interest;
  410.     // so here we do not have to worry about whether the back buffer is oriented vertically or horizontally
  411.     //
  412.     //////////
  413.     
  414.     // the application data structure holds the desired width, center, size, and scale of the movie
  415.     myWidth = (**myAppData).fMovieWidth * (**myAppData).fMovieScale;
  416.     myHeight = myWidth * (((float)(**myAppData).fMovieBox.bottom) / ((float)(**myAppData).fMovieBox.right));
  417.     
  418.     if ((**myAppData).fUseMovieCenter) {
  419.         // use the stored movie center
  420.         myArea.panAngle = (**myAppData).fMovieCenter.x + (myWidth/2);
  421.         myArea.tiltAngle = (**myAppData).fMovieCenter.y + (myHeight/2);
  422.     } else {
  423.         // center the movie on the current pan and tilt angles
  424.         myArea.panAngle = QTVRGetPanAngle(theInstance) + (myWidth/2);
  425.         myArea.tiltAngle = QTVRGetTiltAngle(theInstance) + (myHeight/2);
  426.     }
  427.  
  428.     myArea.width = myWidth;
  429.     myArea.height = myHeight;
  430.  
  431.     //////////
  432.     //
  433.     // set the back buffer flags and install the back buffer procedure
  434.     //
  435.     //////////
  436.     
  437.     // make sure we get called on every idle event, so we can keep playing the embedded movie;
  438.     // also make sure we get called on every back buffer update
  439.     if ((**myAppData).fCompositeMovie)
  440.         myArea.flags = kQTVRBackBufferEveryIdle | kQTVRBackBufferEveryUpdate | kQTVRBackBufferAlwaysRefresh;
  441.     else
  442.         myArea.flags = kQTVRBackBufferEveryIdle | kQTVRBackBufferEveryUpdate;
  443.     
  444.     // if the back buffer is oriented horizontally, set the appropriate flag
  445.     if ((**myAppData).fBackBufferIsHoriz)
  446.         myArea.flags |= kQTVRBackBufferHorizontal;
  447.  
  448.     // install our procedure
  449.     myErr = QTVRSetBackBufferImagingProc(theInstance, (**myAppData).fBackBufferProc, 1, &myArea, (SInt32)theWindowObject);
  450.  
  451.     HUnlock((Handle)myAppData);
  452.     return(myErr);
  453. }
  454.     
  455.     
  456. //////////
  457. //
  458. // VRMoov_CalcImagingMatrix
  459. // Calculate the movie matrix required to draw the embedded movie into the specified rectangle.
  460. //
  461. //////////
  462.  
  463. OSErr VRMoov_CalcImagingMatrix (WindowObject theWindowObject, Rect *theBBufRect)
  464. {
  465.     ApplicationDataHdl        myAppData = NULL;
  466.     Rect                    myDestRect = *theBBufRect;
  467.  
  468.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  469.     if (myAppData == NULL) 
  470.         return(paramErr);
  471.         
  472.     // reset the current movie matrix with the original movie matrix of the embedded movie;
  473.     // we need to preserve that matrix in our calculations below if we are not drawing the
  474.     // movie into an offscreen GWorld
  475.     (**myAppData).fMovieMatrix = (**myAppData).fOrigMovieMatrix;
  476.     
  477.     // in general, it's easiest to construct the desired matrix by first doing the scaling
  478.     // and then doing the rotation and translation (if necessary); so we need to swap the
  479.     // right and bottom edges of the back buffer rectangle before doing the scaling, if a
  480.     // rotation will also be necessary
  481.     if (!(**myAppData).fBackBufferIsHoriz) {
  482.         myDestRect.bottom = theBBufRect->right;
  483.         myDestRect.right = theBBufRect->bottom;
  484.     }
  485.     
  486.     // set up the scaling matrix
  487.     // (MapMatrix concatenates the new matrix to the existing matrix, whereas RectMatrix first
  488.     // sets the existing matrix to the identity matrix)
  489.     if ((**myAppData).fUseOffscreenGWorld)
  490.         RectMatrix(&(**myAppData).fMovieMatrix, &(**myAppData).fMovieBox, &myDestRect);
  491.     else
  492.         MapMatrix(&(**myAppData).fMovieMatrix, &(**myAppData).fMovieBox, &myDestRect);
  493.  
  494.     // add a rotation and translation, if necessary
  495.     if (!(**myAppData).fBackBufferIsHoriz) {
  496.         RotateMatrix(&(**myAppData).fMovieMatrix, Long2Fix(-90), 0, 0);
  497.         TranslateMatrix(&(**myAppData).fMovieMatrix, 0, Long2Fix(RECT_HEIGHT(*theBBufRect)));
  498.     }
  499.  
  500. //    Delay(1, NULL);        // TESTING TESTING 
  501.     
  502.     return(noErr);
  503. }
  504.  
  505.  
  506. //////////
  507. //
  508. // VRMoov_SetupDecompSeq
  509. // Set up the decompression sequence for DecompressionSequenceFrameS.
  510. //
  511. // This needs to be called whenever either the rectangle or the GWorld of the back buffer changes.
  512. //
  513. //////////
  514.  
  515. OSErr VRMoov_SetupDecompSeq (WindowObject theWindowObject, GWorldPtr theDestGWorld)
  516. {
  517.     ApplicationDataHdl        myAppData = NULL;
  518.     short                    myMode = srcCopy;
  519.     OSErr                    myErr = noErr;
  520.     
  521.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  522.     if (myAppData == NULL) 
  523.         return(paramErr);
  524.     
  525.     // make sure we don't have a decompression sequence already open
  526.     VRMoov_RemoveDecompSeq(theWindowObject);
  527.     
  528.     // set up the transfer mode
  529.     if ((**myAppData).fCompositeMovie)
  530.         myMode = srcCopy | transparent;
  531.         
  532.     // set up the image decompression sequence
  533.     myErr = DecompressSequenceBegin(    &(**myAppData).fImageSequence,
  534.                                         (**myAppData).fImageDesc,
  535.                                         (CGrafPtr)theDestGWorld,
  536.                                         NULL,
  537.                                         NULL,                            // entire source image
  538.                                         &(**myAppData).fMovieMatrix,
  539.                                            myMode,
  540.                                         NULL,                            // no mask
  541.                                         0,
  542.                                         (**(**myAppData).fImageDesc).spatialQuality,
  543.                                         NULL);
  544.                                     
  545.     return(myErr);
  546. }
  547.  
  548.  
  549. //////////
  550. //
  551. // VRMoov_RemoveDecompSeq
  552. // Remove the decompression sequence for DecompressionSequenceFrameS.
  553. //
  554. //////////
  555.  
  556. OSErr VRMoov_RemoveDecompSeq (WindowObject theWindowObject)
  557. {
  558.     ApplicationDataHdl        myAppData = NULL;
  559.     OSErr                    myErr = paramErr;
  560.     
  561.     if (theWindowObject != NULL) {
  562.         myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  563.         if (myAppData != NULL) 
  564.             if ((**myAppData).fImageSequence != 0) {
  565.                 myErr = CDSequenceEnd((**myAppData).fImageSequence);
  566.                 (**myAppData).fImageSequence = 0;
  567.             }
  568.     }
  569.     
  570.     return(myErr);
  571. }
  572.  
  573.  
  574. //////////
  575. //
  576. // VRMoov_BackBufferImagingProc
  577. // The back buffer imaging procedure: get a frame of movie and image it into the back buffer.
  578. // Also, do any additional compositing that might be desired.
  579. //
  580. //////////
  581.  
  582. PASCAL_RTN OSErr VRMoov_BackBufferImagingProc (QTVRInstance theInstance, Rect *theRect, UInt16 theAreaIndex, UInt32 theFlagsIn, UInt32 *theFlagsOut, WindowObject theWindowObject)
  583. {
  584. #pragma unused(theAreaIndex)
  585.  
  586.     ApplicationDataHdl        myAppData = NULL;
  587.     Movie                    myMovie = NULL;
  588.     Boolean                    myIsDrawing = theFlagsIn & kQTVRBackBufferRectVisible;
  589.     GWorldPtr                myBBufGWorld, myMovGWorld;
  590.     GDHandle                myBBufGDevice, myMovGDevice;
  591.     Rect                    myRect;
  592.     OSErr                    myErr = paramErr;
  593.     
  594.     //////////
  595.     //
  596.     // initialize; make sure that we've got the data we need to continue
  597.     //
  598.     //////////
  599.  
  600.     // assume we're not going to draw anything
  601.     *theFlagsOut = 0;
  602.     
  603.     if ((theInstance == NULL) || (theWindowObject == NULL)) 
  604.         goto bail;
  605.  
  606.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  607.     if (myAppData == NULL) 
  608.         goto bail;
  609.  
  610.     HLock((Handle)myAppData);
  611.  
  612.     myMovie = (**myAppData).fMovie;
  613.     if (myMovie == NULL) {
  614.         // we don't have an embedded movie, so remove this back-buffer imaging procedure
  615.         VRMoov_DumpEmbeddedMovie(theWindowObject);
  616.         goto bail;
  617.     }
  618.     
  619.     //////////
  620.     //
  621.     // make sure that the movie GWorld is set correctly;
  622.     // note that we call SetMovieGWorld only if we have to (for performance reasons)
  623.     //
  624.     //////////
  625.     
  626.     // get the current graphics world
  627.     // (on entry, the current graphics world is [usually] set to the back buffer)
  628.     GetGWorld(&myBBufGWorld, &myBBufGDevice);
  629.  
  630.     // get the embedded movie's graphics world
  631.     GetMovieGWorld(myMovie, &myMovGWorld, &myMovGDevice);
  632.  
  633.     if ((**myAppData).fUseOffscreenGWorld) {
  634.         // we're using an offscreen graphics world, so set movie's GWorld to be that offscreen graphics world
  635.         if (myMovGWorld != (**myAppData).fOffscreenGWorld)
  636.             SetMovieGWorld(myMovie, (**myAppData).fOffscreenGWorld, GetGWorldDevice((**myAppData).fOffscreenGWorld));            
  637.     } else {
  638.         // we're not using an offscreen graphics world, so set movie GWorld to be the back buffer;
  639.         if ((myMovGWorld != myBBufGWorld) || (myMovGDevice != myBBufGDevice))
  640.             SetMovieGWorld(myMovie, myBBufGWorld, myBBufGDevice);
  641.     }
  642.  
  643.     //////////
  644.     //
  645.     // make sure the movie rectangle and movie matrix are set correctly
  646.     //
  647.     //////////
  648.     
  649.     if (myIsDrawing) {
  650.         // if we weren't previously visible, make sure we are now
  651.         GetMovieBox(myMovie, &myRect);
  652.         if (EmptyRect(&myRect))
  653.             SetMovieBox(myMovie, &(**myAppData).fMovieBox);
  654.         
  655.         // when no offscreen GWorld is being used...
  656.         if (!(**myAppData).fUseOffscreenGWorld) {
  657.             
  658.             // ...make sure the movie matrix is set correctly...
  659.             if (!MacEqualRect(theRect, &(**myAppData).fPrevBBufRect)) {
  660.                 VRMoov_CalcImagingMatrix(theWindowObject, theRect);
  661.                 SetMovieMatrix(myMovie, &(**myAppData).fMovieMatrix);
  662.             }
  663.             
  664.             // ...and, if we are compositing, force QuickTime to draw a movie frame when MoviesTask is called
  665.             // (since the previous frame was automatically erased from the back buffer by QuickTime VR)
  666.             if ((**myAppData).fCompositeMovie)
  667.                 UpdateMovie(myMovie);
  668.         }
  669.         
  670.     } else {
  671.         // if we're not visible, set the movie rectangle to an empty rectangle
  672.         // so we're not wasting time trying to draw a movie frame
  673.         MacSetRect(&myRect, 0, 0, 0, 0);
  674.         SetMovieBox(myMovie, &myRect);
  675.     }
  676.  
  677.     //////////
  678.     //
  679.     // draw a new movie frame into the movie's graphics world (and play movie sound)
  680.     //
  681.     //////////
  682.     
  683.     MoviesTask(myMovie, 1L);
  684. //    MoviesTask(myMovie, 0);
  685.     
  686.     // if we got here, everything is okay so far
  687.     myErr = noErr;
  688.     
  689.     //////////
  690.     //
  691.     // perform any additional compositing
  692.     //
  693.     //////////
  694.     
  695.     // that is, draw, using the current chroma key color, anything to be dropped out of the image;
  696.     // note that this technique works *only* if we're using an offscreen graphics world
  697.     if ((**myAppData).fUseOffscreenGWorld && (**myAppData).fCompositeMovie && myIsDrawing) {
  698.         RGBColor    myColor;
  699.     
  700.         // since we're using an offscreen graphics world, make sure we draw there
  701.         SetGWorld((**myAppData).fOffscreenGWorld, GetGWorldDevice((**myAppData).fOffscreenGWorld));
  702.  
  703.         // set up compositing environment
  704.         GetForeColor(&myColor);
  705.         RGBForeColor(&(**myAppData).fChromaColor);
  706.         
  707.         // do the drawing
  708.         if ((**myAppData).fHideRegion != NULL)
  709.             MacPaintRgn((**myAppData).fHideRegion);
  710.             
  711.         // restore original drawing environment
  712.         RGBForeColor(&myColor);
  713.         
  714.         // restore original graphics world
  715.         SetGWorld(myBBufGWorld, myBBufGDevice);
  716.     }
  717.  
  718.     //////////
  719.     //
  720.     // if we're using an offscreen graphics world, copy it into the back buffer
  721.     //
  722.     //////////
  723.     
  724.     if (myIsDrawing) {
  725.     
  726.         if ((**myAppData).fUseOffscreenGWorld) {
  727.             PixMapHandle    myPixMap;
  728.             
  729.             // if anything relevant to DecompressSequenceFrameS has changed, reset the decompression sequence
  730.             if ((myBBufGWorld != (**myAppData).fPrevBBufGWorld) || !(MacEqualRect(theRect, &(**myAppData).fPrevBBufRect))) {
  731.                 VRMoov_CalcImagingMatrix(theWindowObject, theRect);
  732.                 VRMoov_SetupDecompSeq(theWindowObject, myBBufGWorld);
  733.             }
  734.             
  735.             myPixMap = GetGWorldPixMap((**myAppData).fOffscreenGWorld);
  736.             LockPixels(myPixMap);
  737.             
  738.             // set the chroma key color, if necessary
  739.             if ((**myAppData).fCompositeMovie)
  740.                 RGBBackColor(&(**myAppData).fChromaColor);
  741.             
  742.             // copy the image from the offscreen graphics world into the back buffer
  743.             myErr = DecompressSequenceFrameS(    (**myAppData).fImageSequence,
  744.                                                 StripAddress(GetPixBaseAddr(myPixMap)),
  745.                                                 (**(**myAppData).fImageDesc).dataSize,
  746.                                                 0,
  747.                                                 NULL,
  748.                                                 NULL);
  749.  
  750.             // reset the chroma key color;
  751.             // we need to do this because the buffer we just drew into might NOT actually
  752.             // be the real back buffer (see Virtual Reality Programming With QuickTime VR, p. 1-154);
  753.             // the copy between the intermediate buffer and the back buffer respects the current back color.
  754.             if ((**myAppData).fCompositeMovie)
  755.                 RGBBackColor(&kWhiteColor);
  756.                 
  757.             UnlockPixels(myPixMap);
  758.         }
  759.     }
  760.     
  761.     //////////
  762.     //
  763.     // finish up
  764.     //
  765.     //////////
  766.     
  767.     // keep track of the GWorld and rectangle passed to us this time
  768.     (**myAppData).fPrevBBufGWorld = myBBufGWorld;
  769.     (**myAppData).fPrevBBufRect = *theRect;
  770.     
  771.     // if we drew something, tell QuickTime VR
  772.     if (myIsDrawing)
  773.         *theFlagsOut = kQTVRBackBufferFlagDidDraw;
  774.     
  775. bail:    
  776.     HUnlock((Handle)myAppData);
  777.     return(myErr);
  778. }
  779.  
  780.  
  781. //////////
  782. //
  783. // VRMoov_GetEmbeddedMovieWidth
  784. // Get the width of the embedded movie.
  785. //
  786. //////////
  787.  
  788. float VRMoov_GetEmbeddedMovieWidth (WindowObject theWindowObject)
  789. {
  790.     ApplicationDataHdl        myAppData;
  791.     float                    myWidth;
  792.  
  793.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  794.     if (myAppData == NULL)
  795.         myWidth = 0;
  796.     else
  797.         myWidth = (**myAppData).fMovieWidth;
  798.         
  799.     return(myWidth);
  800. }
  801.  
  802.  
  803. //////////
  804. //
  805. // VRMoov_SetEmbeddedMovieWidth
  806. // Set the width of the embedded movie.
  807. //
  808. //////////
  809.  
  810. void VRMoov_SetEmbeddedMovieWidth (WindowObject theWindowObject, float theWidth)
  811. {
  812.     ApplicationDataHdl        myAppData;
  813.     QTVRInstance            myInstance;
  814.  
  815.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  816.     if (myAppData == NULL)
  817.         return;
  818.         
  819.     myInstance = (**theWindowObject).fInstance;
  820.     if (myInstance == NULL)
  821.         return;
  822.     
  823.     // install the desired width in our application data structure
  824.     (**myAppData).fMovieWidth = theWidth;
  825.     
  826.     // clear out the existing area of interest
  827.     QTVRRefreshBackBuffer(myInstance, 0);
  828.  
  829.     // reinstall the back buffer imaging procedure
  830.     VRMoov_InstallBackBufferImagingProc(myInstance, theWindowObject);
  831. }
  832.  
  833.  
  834. //////////
  835. //
  836. // VRMoov_GetEmbeddedMovieCenter
  837. // Get the center of the embedded movie.
  838. //
  839. //////////
  840.  
  841. void VRMoov_GetEmbeddedMovieCenter (WindowObject theWindowObject, QTVRFloatPoint *theCenter)
  842. {
  843.     ApplicationDataHdl        myAppData;
  844.  
  845.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  846.     if (myAppData == NULL) {
  847.         theCenter->x = 0.0;
  848.         theCenter->y = 0.0;
  849.     } else {
  850.         theCenter->x = (**myAppData).fMovieCenter.x;
  851.         theCenter->y = (**myAppData).fMovieCenter.y;
  852.     }
  853.         
  854. }
  855.  
  856.  
  857. //////////
  858. //
  859. // VRMoov_SetEmbeddedMovieCenter
  860. // Set the center of the embedded movie.
  861. //
  862. //////////
  863.  
  864. void VRMoov_SetEmbeddedMovieCenter (WindowObject theWindowObject, const QTVRFloatPoint *theCenter)
  865. {
  866.     ApplicationDataHdl        myAppData;
  867.     QTVRInstance            myInstance;
  868.     float                    myX, myY;
  869.  
  870.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  871.     if (myAppData == NULL)
  872.         return;
  873.         
  874.     myInstance = (**theWindowObject).fInstance;
  875.     if (myInstance == NULL)
  876.         return;
  877.     
  878.     myX = theCenter->x;
  879.     myY = theCenter->y;
  880.     
  881.     // subject the values passed in to the current view constraints
  882.     QTVRWrapAndConstrain(myInstance, kQTVRPan, myX, &myX);
  883.     QTVRWrapAndConstrain(myInstance, kQTVRTilt, myY, &myY);
  884.             
  885.     // install the desired center in our application data structure
  886.     (**myAppData).fMovieCenter.x = myX;
  887.     (**myAppData).fMovieCenter.y = myY;
  888.     
  889.     // clear out the existing area of interest
  890.     QTVRRefreshBackBuffer(myInstance, 0);
  891.  
  892.     // reinstall the back buffer imaging procedure
  893.     VRMoov_InstallBackBufferImagingProc(myInstance, theWindowObject);
  894. }
  895.  
  896.  
  897. //////////
  898. //
  899. // VRMoov_GetEmbeddedMovieScale
  900. // Get the scale of the embedded movie.
  901. //
  902. //////////
  903.  
  904. float VRMoov_GetEmbeddedMovieScale (WindowObject theWindowObject)
  905. {
  906.     ApplicationDataHdl        myAppData;
  907.     float                    myScale;
  908.  
  909.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  910.     if (myAppData == NULL)
  911.         myScale = 0;
  912.     else
  913.         myScale = (**myAppData).fMovieScale;
  914.         
  915.     return(myScale);
  916. }
  917.  
  918.  
  919. //////////
  920. //
  921. // VRMoov_SetEmbeddedMovieScale
  922. // Set the scale factor of the embedded movie.
  923. //
  924. //////////
  925.  
  926. void VRMoov_SetEmbeddedMovieScale (WindowObject theWindowObject, float theScale)
  927. {
  928.     ApplicationDataHdl        myAppData;
  929.     QTVRInstance            myInstance;
  930.  
  931.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  932.     if (myAppData == NULL)
  933.         return;
  934.         
  935.     myInstance = (**theWindowObject).fInstance;
  936.     if (myInstance == NULL)
  937.         return;
  938.     
  939.     // install the desired scale factor in our application data structure
  940.     (**myAppData).fMovieScale = theScale;
  941.     
  942.     // clear out the existing area of interest
  943.     QTVRRefreshBackBuffer(myInstance, 0);
  944.  
  945.     // reinstall the back buffer imaging procedure
  946.     VRMoov_InstallBackBufferImagingProc(myInstance, theWindowObject);
  947. }
  948.  
  949.  
  950. //////////
  951. //
  952. // VRMoov_SetChromaColor
  953. // Set the chroma key color for a window object:
  954. // display color picker dialog and remember the newly-selected color.
  955. //
  956. //////////
  957.  
  958. void VRMoov_SetChromaColor (WindowObject theWindowObject)
  959. {
  960. #if TARGET_OS_MAC
  961.     ColorPickerInfo        myColorInfo;
  962. #endif    
  963. #if TARGET_OS_WIN32
  964.     static CHOOSECOLOR    myColorRec;
  965.     static COLORREF        myColorRef[16];
  966. #endif    
  967.     ApplicationDataHdl    myAppData;
  968.  
  969.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  970.     if (myAppData == NULL)
  971.         return;
  972.  
  973. #if TARGET_OS_MAC
  974.     // pass in existing color
  975.     myColorInfo.theColor.color.rgb.red = (**myAppData).fChromaColor.red;
  976.     myColorInfo.theColor.color.rgb.green = (**myAppData).fChromaColor.green;
  977.     myColorInfo.theColor.color.rgb.blue = (**myAppData).fChromaColor.blue;
  978.     
  979.     // not much here...
  980.     myColorInfo.theColor.profile = 0L;
  981.     myColorInfo.dstProfile = 0L;
  982.     myColorInfo.flags = 0L;
  983.     myColorInfo.placeWhere = kCenterOnMainScreen;
  984.     myColorInfo.pickerType = 0L;
  985.     myColorInfo.eventProc = gColorFilterUPP;
  986.     myColorInfo.colorProc = NULL;
  987.     myColorInfo.colorProcData = 0L;
  988.     GetIndString(myColorInfo.prompt, kColorPickerTextStringID, 1);
  989.     
  990.     // set Edit menu info
  991.     myColorInfo.mInfo.editMenuID = mEdit;
  992.     myColorInfo.mInfo.undoItem = iUndo;
  993.     myColorInfo.mInfo.cutItem = iCut;
  994.     myColorInfo.mInfo.copyItem = iCopy;
  995.     myColorInfo.mInfo.pasteItem = iPaste;
  996.     myColorInfo.mInfo.clearItem = iClear;
  997.     
  998.     // call Color Picker
  999.     if ((PickColor(&myColorInfo) == noErr) && (myColorInfo.newColorChosen)) {
  1000.         // install the newly chosen color in the palette
  1001.         (**myAppData).fChromaColor.red = myColorInfo.theColor.color.rgb.red;
  1002.         (**myAppData).fChromaColor.green = myColorInfo.theColor.color.rgb.green;
  1003.         (**myAppData).fChromaColor.blue = myColorInfo.theColor.color.rgb.blue;
  1004.     }
  1005. #endif
  1006. #if TARGET_OS_WIN32
  1007.     myColorRec.lStructSize = sizeof(CHOOSECOLOR);
  1008.     myColorRec.hwndOwner = NULL;
  1009.     myColorRec.hInstance = NULL;
  1010.     
  1011.     VRMoov_MacRGBToWinRGB(&(**myAppData).fChromaColor, &(myColorRec.rgbResult));
  1012.     
  1013.     myColorRec.lpCustColors = myColorRef;
  1014.     myColorRec.Flags = CC_RGBINIT | CC_FULLOPEN;
  1015.     myColorRec.lCustData = 0;
  1016.     myColorRec.lpfnHook = NULL;
  1017.     myColorRec.lpTemplateName = NULL;
  1018.     
  1019.     // call Common Color dialog
  1020.     if (ChooseColor(&myColorRec)) {
  1021.         // install the newly chosen color in the palette
  1022.         VRMoov_WinRGBToMacRGB(&(**myAppData).fChromaColor, myColorRec.rgbResult);
  1023.     }
  1024. #endif
  1025. }
  1026.     
  1027.  
  1028. //////////
  1029. //
  1030. // VRMoov_ColorDialogEventFilter
  1031. // Handle events before they get passed to the Color Picker dialog box.
  1032. //
  1033. //////////
  1034.  
  1035. PASCAL_RTN Boolean VRMoov_ColorDialogEventFilter (EventRecord *theEvent)
  1036. {
  1037. #if TARGET_OS_WIN32
  1038. #pragma unused(theEvent)
  1039. #endif
  1040.     Boolean                myEventHandled = false;
  1041.     OSErr                myErr = noErr;
  1042.  
  1043. #if TARGET_OS_MAC
  1044.     switch (theEvent->what) {
  1045.         case updateEvt: {
  1046.             if ((WindowPtr)theEvent->message != FrontWindow()) {
  1047.                 DoUpdateWindow((WindowPtr)theEvent->message, &((WindowPtr)theEvent->message)->portRect);
  1048.                 myEventHandled = true;
  1049.             }
  1050.             break;
  1051.         }
  1052.  
  1053.         case nullEvent: {
  1054.             // do idle-time processing for all open windows in our window list
  1055.             WindowObject        myWindowObject = NULL;
  1056.             ApplicationDataHdl    myAppData = NULL;
  1057.             WindowReference        myWindow = NULL;
  1058.  
  1059.             myWindow = GetFrontMovieWindow();
  1060.             while (myWindow != NULL) {
  1061.                 myWindowObject = (WindowObject)GetWindowObjectFromWindow(myWindow);
  1062.                 myAppData = (ApplicationDataHdl)GetAppDataFromWindow(myWindow);
  1063.                 if ((myWindowObject != NULL) && (myAppData != NULL))
  1064.                     if ((**myAppData).fMovie != NULL)
  1065.                         QTVRUpdate((**myWindowObject).fInstance, kQTVRCurrentMode);
  1066.                 myWindow = GetNextMovieWindow(myWindow);
  1067.             }
  1068.             
  1069.             myEventHandled = false;
  1070.             break;
  1071.         }
  1072.         
  1073.         case kHighLevelEvent:
  1074.             myErr = AEProcessAppleEvent(theEvent);
  1075.             if (myErr != noErr)
  1076.                 myEventHandled = true;
  1077.              break;
  1078.             
  1079.         default:
  1080.             myEventHandled = false;
  1081.             break;
  1082.     }    
  1083.     
  1084. #endif
  1085.     return(myEventHandled);
  1086. }
  1087.  
  1088.  
  1089. //////////
  1090. //
  1091. // VRMoov_UncoverProc
  1092. // The uncover function of the embedded movie.
  1093. //
  1094. //////////
  1095.  
  1096. PASCAL_RTN OSErr VRMoov_UncoverProc (Movie theMovie, RgnHandle theRegion, WindowObject theWindowObject)
  1097. {
  1098. #pragma unused(theMovie, theRegion, theWindowObject)
  1099.     return(noErr);
  1100. }
  1101.  
  1102.  
  1103. //////////
  1104. //
  1105. // VRMoov_SetVideoGraphicsMode
  1106. // Set the video media graphics mode of the embedded movie.
  1107. //
  1108. //////////
  1109.  
  1110. void VRMoov_SetVideoGraphicsMode (Movie theMovie, ApplicationDataHdl theAppData, Boolean theSetVGM)
  1111. {
  1112.     long                myTrackCount;
  1113.     short                myIndex;
  1114.     Track                myTrack = NULL;
  1115.     Media                myMedia = NULL;
  1116.     OSType                myMediaType;
  1117.     
  1118.     if ((theMovie == NULL) || (theAppData == NULL))
  1119.         return;
  1120.     
  1121.     myTrackCount = GetMovieTrackCount(theMovie);
  1122.     for (myIndex = 1; myIndex <= myTrackCount; myIndex++) {
  1123.         myTrack = GetMovieIndTrack(theMovie, myIndex);
  1124.         myMedia = GetTrackMedia(myTrack);
  1125.         GetMediaHandlerDescription(myMedia, &myMediaType, NULL, NULL);
  1126.         if (myMediaType == VideoMediaType) {
  1127.             if (theSetVGM)
  1128.                 MediaSetGraphicsMode(GetMediaHandler(myMedia), srcCopy | transparent, &(**theAppData).fChromaColor);
  1129.             else
  1130.                 MediaSetGraphicsMode(GetMediaHandler(myMedia), srcCopy, &kWhiteColor);
  1131.         }
  1132.     }
  1133.     
  1134.     return;
  1135. }
  1136.  
  1137.  
  1138. //////////
  1139. //
  1140. // VRMoov_GetVideoGraphicsPixelDepth
  1141. // Return the highest pixel depth supported by a QuickTime movie.
  1142. //
  1143. //////////
  1144.  
  1145. short VRMoov_GetVideoGraphicsPixelDepth (Movie theMovie)
  1146. {
  1147.     long                myTrackCount;
  1148.     short                myIndex;
  1149.     Track                myMovieTrack = NULL;
  1150.     Media                myMedia;
  1151.     OSType                myMediaType;
  1152.     short                myQuality;
  1153.     
  1154.     myTrackCount = GetMovieTrackCount(theMovie);
  1155.     for (myIndex = 1; myIndex <= myTrackCount; myIndex++) {
  1156.         myMovieTrack = GetMovieIndTrack(theMovie, myIndex);
  1157.         myMedia = GetTrackMedia(myMovieTrack);
  1158.         GetMediaHandlerDescription(myMedia, &myMediaType, NULL, NULL);
  1159.         if (myMediaType == VideoMediaType) {
  1160.             myQuality = GetMediaQuality(myMedia);
  1161.             if (myQuality >> 5)
  1162.                 return(32);
  1163.             if (myQuality >> 4)
  1164.                 return(16);
  1165.             if (myQuality >> 3)
  1166.                 return(8);
  1167.             if (myQuality >> 2)
  1168.                 return(4);
  1169.             if (myQuality >> 1)
  1170.                 return(2);
  1171.             if (myQuality >> 0)
  1172.                 return(1);
  1173.         }
  1174.     }
  1175.     
  1176.     return(0);
  1177. }
  1178.  
  1179.  
  1180. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1181. //
  1182. // Color conversion utilities.
  1183. //
  1184. // Macintosh usually represents colors using an RGBColor structure, where each color component is a 16-bit
  1185. // unsigned integer. Windows represents colors using a 32-bit unsigned COLORREF, where each color component
  1186. // occupies 8 bits. The following two functions allow us to convert from Mac to Windows colors and back. We
  1187. // need to do this because we use Mac-style colors when doing compositing.
  1188. //
  1189. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1190.  
  1191. #if TARGET_OS_WIN32
  1192.  
  1193. #define kMaxMacRGBValue                0xffff
  1194. #define kMaxWinRGBValue                0x00ff
  1195. #define MAC_TO_WIN_COMP(color)        (color*((float)kMaxWinRGBValue/(float)kMaxMacRGBValue))
  1196. #define WIN_TO_MAC_COMP(color)        (color*((float)kMaxMacRGBValue/(float)kMaxWinRGBValue))
  1197.  
  1198.  
  1199. //////////
  1200. //
  1201. // VRMoov_MacRGBToWinRGB
  1202. // Convert an RGBColor structure into a COLORREF value.
  1203. //
  1204. //////////
  1205.  
  1206. void VRMoov_MacRGBToWinRGB (RGBColorPtr theRGBColor, COLORREF *theColorRef)
  1207. {
  1208.     *theColorRef = RGB(    (BYTE)MAC_TO_WIN_COMP(theRGBColor->red),
  1209.                         (BYTE)MAC_TO_WIN_COMP(theRGBColor->green),
  1210.                         (BYTE)MAC_TO_WIN_COMP(theRGBColor->blue));
  1211. }
  1212.  
  1213.  
  1214. //////////
  1215. //
  1216. // VRMoov_WinRGBToMacRGB
  1217. // Convert a COLORREF value into an RGBColor structure.
  1218. //
  1219. //////////
  1220.  
  1221. void VRMoov_WinRGBToMacRGB (RGBColorPtr theRGBColor, COLORREF theColorRef)
  1222. {
  1223.     theRGBColor->red = (unsigned long)WIN_TO_MAC_COMP(GetRValue(theColorRef));
  1224.     theRGBColor->green = (unsigned long)WIN_TO_MAC_COMP(GetGValue(theColorRef));
  1225.     theRGBColor->blue = (unsigned long)WIN_TO_MAC_COMP(GetBValue(theColorRef));
  1226. }
  1227. #endif    // TARGET_OS_WIN32
  1228.  
  1229.  
  1230.